home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / Venus / main.cc < prev    next >
C/C++ Source or Header  |  1996-06-22  |  8KB  |  263 lines

  1. /*
  2.  ************************************************************************
  3.  *
  4.  *                               Root Module
  5.  * Note on animation.
  6.  * We don't use null events to do animation: all animation is done in the
  7.  * drawing function itself. To activate animation, we invalidate regions
  8.  * covering both 2d and 3d views, and set is_flying to TRUE. Invalidating regions
  9.  * guarantees that visRgn of our on-screen window is set to include both views,
  10.  * and it makes sure that the next event would be an Update event. This event
  11.  * is eventually relayed to our 2d_view's and 3d_view's drawing functions.
  12.  * When is_flying is set to TRUE, these functions not only draw a window, but
  13.  * perform a few cycles of animation as well. Before they return, they invalidate
  14.  * the regions again, thus making sure that a new Update event would be generated,
  15.  * and they'll be called again.
  16.  *
  17.  ************************************************************************
  18.  */
  19.  
  20. #include "fractal_map.h"
  21. #include "mymenv.h"
  22. #include "EventHandlers.h"
  23. #include "ValueControl.h"
  24. #include "ImageViews.h"
  25. #include "filter.h"
  26. //#include "profiler.h"
  27.  
  28. class VenusDialog : public ModelessDialog
  29. {
  30.   enum { item_Go = 1, item_Cancel = 2, item_2dview = 3, item_3dview = 4,
  31.            item_ze=5,   item_ze_val=6,   item_ze_text=7,
  32.            item_beta=8, item_beta_val=9, item_beta_text=10,
  33.            item_Ou=11,  item_Ou_val=12,  item_Ou_text=13,
  34.            item_Ov=14,  item_Ov_val=15,  item_Ov_text=16,
  35.            item_zc=17,  item_zc_val=18,  item_zc_text=19,
  36.            item_zf=20,  item_zf_val=21,  item_zf_text=22,
  37.            item_fps=24 };
  38.   enum { dlog_id = 128 };
  39.  
  40.   ProjectionParameters projection_parms;
  41.   Boolean handle_item_hit(const int item_no);
  42.   Boolean handle_activate(Boolean onoff);    // Handle suspend/resume events
  43.  
  44.   ValueControl eyepoint_elevation;
  45.   ValueControl beta;                    // Local coordinates scaling factor
  46.   ValueControl Ou;                        // Origin of the local coordinate ref Pt
  47.   ValueControl Ov;
  48.   ValueControl z_cutoff;                // Coefficients to determine elevation from
  49.   ValueControl elevation_factor;        // the map's "elevation code"
  50.  
  51.   int    time_started;                    // Time (ticks) started flying the last time
  52.   int    frame_counter;
  53.   
  54.   ImageView image_2d_view;
  55.   ThreeDView image_3d_view;
  56.   void draw_user_item(const int item_no);
  57.   void start_flight(void);
  58.   void stop_flight(void);
  59.   
  60.   Boolean is_flying;                    // Is our plane moving?
  61.  
  62. public:
  63.   VenusDialog(const IMAGE& image);
  64. };
  65.  
  66. VenusDialog::VenusDialog(const IMAGE& image)
  67.     : ModelessDialog(dlog_id), image_2d_view(image), 
  68.       image_3d_view(image,image_2d_view.where_is_viewer(),projection_parms),
  69.       beta(4,1), is_flying(FALSE)
  70. {
  71.                                         // Late construction of items, after the dialog itself
  72.                                         // has been initialized
  73.   image_2d_view.bind(*this,item_2dview);
  74.   eyepoint_elevation.bind(ControlItem(*this,item_ze),NumberItem(*this,item_ze_val));
  75.   beta.bind(ControlItem(*this,item_beta),NumberItem(*this,item_beta_val));
  76.   Ou.bind(ControlItem(*this,item_Ou),NumberItem(*this,item_Ou_val));
  77.   Ov.bind(ControlItem(*this,item_Ov),NumberItem(*this,item_Ov_val));
  78.   z_cutoff.bind(ControlItem(*this,item_zc),NumberItem(*this,item_zc_val));
  79.   elevation_factor.bind(ControlItem(*this,item_zf),NumberItem(*this,item_zf_val));
  80.   
  81.   NumberItem(*this,item_fps).draw(0);
  82.   
  83.   projection_parms.ze = eyepoint_elevation;
  84.   projection_parms.beta = beta;
  85.   projection_parms.Ou   = Ou;
  86.   projection_parms.Ov   = Ov;
  87.   projection_parms.z_cutoff = z_cutoff;
  88.   projection_parms.elevation_factor = elevation_factor;
  89.  
  90.   image_3d_view.bind(*this,item_3dview);
  91.   
  92.   show();
  93. }
  94.  
  95.                                 // Commencing and terminating the flight
  96. void VenusDialog::start_flight(void)
  97. {
  98.   is_flying = TRUE;
  99.   ModelessDialog::ControlItem(*this,item_Go).set_title("\pStop");
  100.   frame_counter = 0;
  101.   time_started = TickCount();
  102. }
  103.  
  104. void VenusDialog::stop_flight(void)
  105. {
  106.   is_flying = FALSE;
  107.   ModelessDialog::ControlItem(*this,item_Go).set_title("\pGo");
  108.   const int time_elapsed = TickCount() - time_started;    // in Ticks
  109.   NumberItem(*this,item_fps).draw(
  110.           time_elapsed == 0 ? 0 : (60*frame_counter)/time_elapsed );
  111. }
  112.  
  113. Boolean VenusDialog::handle_item_hit(const int item_no)
  114. {
  115.   SetNewGrafPtr dialog_grafport(our_window());
  116.   switch(item_no)
  117.   {
  118.     case item_Cancel:
  119.          return FALSE;
  120.  
  121.     case item_ze:
  122.          projection_parms.ze = eyepoint_elevation;
  123.          image_3d_view.re_project();
  124.          return TRUE;
  125.          
  126.     case item_beta:
  127.          projection_parms.beta = beta;
  128.          image_3d_view.re_project();
  129.          return TRUE;
  130.          
  131.     case item_Ou:
  132.          projection_parms.Ou = Ou;
  133.          image_3d_view.re_project();
  134.          return TRUE;
  135.          
  136.     case item_Ov:
  137.          projection_parms.Ov = Ov;
  138.          image_3d_view.re_project();
  139.          return TRUE;
  140.          
  141.     case item_zc:
  142.          projection_parms.z_cutoff = z_cutoff;
  143.          image_3d_view.re_project();
  144.          return TRUE;
  145.          
  146.     case item_zf:
  147.          projection_parms.elevation_factor = elevation_factor;
  148.          image_3d_view.re_project();
  149.          return TRUE;
  150.          
  151.     case item_Go:
  152.          if( is_flying )
  153.            stop_flight();
  154.          else
  155.            start_flight();
  156.           image_2d_view.force_redraw();
  157.           image_3d_view.force_redraw();
  158.          return TRUE;
  159.          
  160.     default:
  161.          return TRUE;
  162.   }
  163. }
  164.  
  165.                                         // A relay to draw specific user items
  166.                                         // See a note on animation above
  167. void VenusDialog::draw_user_item(const int item_no)
  168. {
  169.   const int turns_per_cycle = 30;
  170.   switch(item_no)
  171.   {
  172.     case item_2dview:
  173.          if( is_flying )
  174.          {
  175.            for(register int i=0; i<turns_per_cycle; i++)
  176.                   image_2d_view.do_one_turn(),
  177.                image_3d_view.re_project();
  178.             image_2d_view.force_redraw();        // That would make sure that the next call
  179.             image_3d_view.force_redraw();        // to WaitNextEvent would get another update
  180.            frame_counter += turns_per_cycle;
  181.           }                                        // event, and this function would be called again
  182.          else
  183.           image_2d_view.draw();
  184.          break;
  185.     case item_3dview:
  186.          if( !is_flying )                        // when flying, the window has been
  187.            image_3d_view.draw();                // already redrawn, see case above
  188.          break;
  189.     default:
  190.          _die("couldn't draw user item %d",item_no);
  191.   }
  192. }
  193.  
  194.  
  195.                                         // Handle suspend/resume events: stop flying on
  196.                                         // a suspend event (flying takes too much time,
  197.                                         // it's unreasonable to take so much when
  198.                                         // running in background)
  199. Boolean VenusDialog::handle_activate(Boolean onoff)
  200. {
  201.   if( !onoff && is_flying )
  202.     handle_item_hit(item_Go);
  203.   return TRUE; 
  204. }
  205.  
  206.                                         // Making elevation maps to fly around to
  207.                                         
  208. class MakeTestImage : public LazyImage    // this one makes a couple of pyramids
  209. {
  210.   void fill_in(IMAGE& im) const
  211.   {
  212.     const int ncols = im.q_ncols();
  213.     for(register int j=-20; j<20; j++)
  214.       for(register int i=-5; i<5; i++)
  215.         im(64+i,j+ncols/2) = 128 - 5*abs(i+j),
  216.         im(64+40+i,j+ncols/2) = 180 - 7*abs(i+j);
  217.   }
  218. public:
  219.   MakeTestImage(void) : LazyImage(256,256,8) {}
  220. };
  221.  
  222. class GaussClouds : public FractalMap
  223. {
  224.   public:
  225.     GaussClouds(const card order)
  226.       : FractalMap(order) {}
  227.                 // Well-known Gaussian random number generator
  228.                 // Note rand() returns a number [0,2^15-1],
  229.                 // that is, within [0,1] with a 15-bit implicit
  230.                 // fraction
  231.     inline int get_noise(const card scale) const {
  232.       long sum = 0;
  233.       for(register int i=0; i<12; i++)
  234.          sum += rand();            // keep the result within 
  235.       return (scale * (sum-(6<<15)))>>17; }    // [-scale/2,scale/2]
  236. };
  237.  
  238. void main(void)
  239. {
  240.   Initialize_MAC();
  241.  
  242.   GetDateTime((unsigned long *)&qd.randSeed);
  243.   Random(); Random(); Random();                     // Just randomizing
  244.   srand(qd.randSeed);
  245. #if 1
  246.   IMAGE image = FractalMap(8);                    // Get gaussian clouds and smooth them a bit
  247. //  IMAGE image = GaussClouds(8);                    // Get gaussian clouds and smooth them a bit
  248.   FilterIt(image).conv(conv_kernel(1,1,1,CommonDenom(3))).clip_to_intensity_range();
  249. #else
  250. //  IMAGE image = FractalMap(8);  
  251.   IMAGE image = MakeTestImage();
  252. #endif
  253.   VenusDialog venus_dialog(image);
  254.   EventHandler event_handler(venus_dialog,0);
  255.   
  256.   //ProfilerInit(collectDetailed,bestTimeBase,150,15);
  257.   //ProfilerSetStatus(0);
  258.   event_handler.loop();
  259.   //ProfilerDump("\pprofiler info");
  260.   //ProfilerTerm();
  261. //  alert("Done");
  262. }
  263.